`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:  X-Speed.com.cn
// Engineer: yansf
// 
// Create Date:    01/18/2024
// Design Name: 
// Module Name:    CPU_Interface 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

module CPU_Interface(
	//----------------clk and rst-------------
	Clk, 
	nRst,
	//----------------i2c---------------------
	I2C_SCL_SLAVE, 
	I2C_SDA_SLAVE,
	//----------------harware config----------
	Board_Ver,
	BYPASS_STATUS_IN,
	//----------------reset reason input signal
	b_WDT_OverTime,
	nReq_Reset,
	n_Rst_Botton_Reset, 
	// ---- Output Regs -----
	r_Watchdog_Time,
	r_WDT_Feed, 
	r_WDT_En, 
	//-----bypass ctrl
	r_Bypass_Control, 
	// ---- Debug --------------- 
	WDT_Time_Cnt,
	//-----COM1,COM2 console mode ctrl reg
	r_Console_Com1_Mode_Ctrl,
	r_Console_Com2_Mode_Ctrl,
	//-----error terminal
	r_error_terminal_en,
	//-----error signal
	bp_vol_error,
	com1_mode_error,
	com2_mode_error,
	//-----reset cause clear bit
	rst_reason_clr,
	//-----
	Com2_Console_mode_det,
	Com1_Console_mode_det
);

input 				Clk;
input 				nRst;
input 				I2C_SCL_SLAVE;
inout 				I2C_SDA_SLAVE;
input 				BYPASS_STATUS_IN;
input 	[2:0]		Com2_Console_mode_det;
input 	[2:0]		Com1_Console_mode_det;

// ---------------------Debug----------------------------
input [7:0] 		WDT_Time_Cnt;

// ---------------------board config---------------------
input [3:0] 		Board_Ver;

// ---------------------reset reason---------------------
input 				b_WDT_OverTime;
input  				nReq_Reset;
input  				n_Rst_Botton_Reset;

//----------------------
input 				bp_vol_error;
input				com1_mode_error;
input				com2_mode_error;

//----------------------hardware watchdog
output [7:0] 		r_Watchdog_Time;
output 				r_WDT_Feed;
output				r_WDT_En;

//----------------------BYPASS ctrl
output 				r_Bypass_Control;

//---------------------error terminal
output 				r_error_terminal_en;

//---------------------
output 				rst_reason_clr;

//---------------------console mode ctrl output 
output 	[1:0]		r_Console_Com1_Mode_Ctrl;
output 	[1:0]		r_Console_Com2_Mode_Ctrl;


// --------------------i2c signals-----------------------
wire [6:0] 			fpga_device_addr  = 7'h61;	// i2c slave addr
wire 				i2c_rd_request;		// read request
wire [7:0] 			i2c_rd_wr_addr;	// I2C read or write address
wire 				i2c_wr_data_valid;		// I2C write valid
wire [7:0] 			i2c_wr_data;		// I2c write data
wire 				i2c_rd_wr_sign;		// read or write
reg 				i2c_data_rd_valid;		// I2C read valid
reg [7:0] 			i2c_rd_data = 8'h0;		// I2C read data
reg [7:0] 			i2c_rd_data_reg;	// I2C read data temporary 
reg 				rd_en;		// I2C read Enable

// -------------------------------- Definde of User's Regs ----------------
parameter 			ADDR_FPGA_Vertion = 7'h00;
parameter 			ADDR_Board_Config = 7'h02;
parameter 			ADDR_Watchdog_Time = 7'h03;
parameter 			ADDR_Watchdog_Ctrl = 7'h06;
parameter 			ADDR_Console_Mode_Ctrl = 7'h08;
parameter 			ADDR_Bypass_Set = 7'h09;
parameter 			ADDR_Bypass_Status = 7'h0A;
parameter 			ADDR_Console_Current_Status = 7'h0B;
parameter 			ADDR_ERROR_TERMINAL_CTRL = 7'h0C;
parameter 			ADDR_ERROR_REASON = 7'h0D;
parameter 			ADDR_RESET_REASON = 7'h0E;

// ------------- Debug
parameter 			ADDR_WDT_Time_Cnt = 7'h0F;

// ------------- FPGA  Version ----------------
parameter 			FPGA_VERSION = 8'b00_000_011;		// V0_0_3
/* -------------- Version Comments -------------------------
V001:

-------------------------------------------------------------*/

// -------------Watchdog------------------------------------
reg [7:0] 			r_Watchdog_Time = 8'd255;	// default 255 Secondes
reg 				r_WDT_Feed = 1'b1;
reg 				r_WDT_En = 1'b0;


//---------- bypass reg -------------------------------------     
reg 				r_Bypass_Control;

// ------------ debug --------------------------------------
reg [7:0] 			r_Debug_CntTime = 8'h00;

//-------------error terminal
reg  				r_error_terminal_en;

//-------------console mode set
reg		[1:0]		r_Console_Com1_Mode_Ctrl;
reg		[1:0]		r_Console_Com2_Mode_Ctrl;

//-------------reset cause clear 
reg					rst_reason_clr;

//-------------power drop record-----
reg					power_on_ok = 1'b0;
//******************************************************
// I2C Slave Write
always @( posedge Clk or negedge nRst)  
begin  
	if (~nRst)
	begin
		r_Watchdog_Time <= 8'd255;
		r_WDT_Feed <= 1'b1;
		r_WDT_En <= 1'b0;
		r_Bypass_Control  <= 1'b1;
		r_Console_Com1_Mode_Ctrl <= 2'b00;
		r_Console_Com2_Mode_Ctrl <= 2'b00;
		r_error_terminal_en <= 1'b0;
		rst_reason_clr		<= 1'b0;
		r_Debug_CntTime		<= 8'h00;
	end
	else if ( i2c_wr_data_valid )
				case(i2c_rd_wr_addr[6:0])
			ADDR_Watchdog_Time		:	
				begin
					r_Watchdog_Time <= i2c_wr_data;
				end			
			ADDR_Watchdog_Ctrl		:
				begin
					{r_WDT_Feed, r_WDT_En} <= i2c_wr_data[1:0];
				end
			ADDR_Console_Mode_Ctrl  :
				begin
					r_Console_Com1_Mode_Ctrl <= i2c_wr_data[1:0];
					r_Console_Com2_Mode_Ctrl <= i2c_wr_data[3:2];
				end				
			ADDR_Bypass_Set			:	
				begin
					r_Bypass_Control <= i2c_wr_data[0];
				end			
			ADDR_ERROR_TERMINAL_CTRL	:
				begin
					r_error_terminal_en <= i2c_wr_data[0];
				end
			ADDR_RESET_REASON		:
				begin
					rst_reason_clr <=  i2c_wr_data[7];
					power_on_ok <=  i2c_wr_data[3];
				end
			default: ;
		endcase
	else
		begin
			r_Watchdog_Time  <= r_Watchdog_Time;
		end
end

// I2C Slave Read
always @( posedge Clk )
begin
	case ( i2c_rd_wr_addr[6:0] )
		ADDR_FPGA_Vertion		:	i2c_rd_data_reg <= FPGA_VERSION;
		ADDR_Board_Config		:	i2c_rd_data_reg <= { 4'b0000, Board_Ver };
		ADDR_Watchdog_Time		:	i2c_rd_data_reg <= r_Watchdog_Time;
		ADDR_Watchdog_Ctrl		:	i2c_rd_data_reg <= { 6'b0000_00, r_WDT_Feed, r_WDT_En };
		ADDR_Console_Mode_Ctrl  :   i2c_rd_data_reg <= { 4'b0000, r_Console_Com2_Mode_Ctrl, r_Console_Com1_Mode_Ctrl };
		ADDR_Bypass_Set			:	i2c_rd_data_reg <= { 7'b00_0000, r_Bypass_Control};
		ADDR_Bypass_Status      :	i2c_rd_data_reg <= { 7'b000_0000, BYPASS_STATUS_IN };
		ADDR_Console_Current_Status :	i2c_rd_data_reg <= { 2'b00, Com2_Console_mode_det, Com1_Console_mode_det };
		ADDR_ERROR_TERMINAL_CTRL	:	i2c_rd_data_reg <= { 7'b000_0000, r_error_terminal_en };
		ADDR_ERROR_REASON		:	i2c_rd_data_reg <= { 4'b0000, com2_mode_error, com1_mode_error, bp_vol_error };
		ADDR_RESET_REASON		:	i2c_rd_data_reg <= { rst_reason_clr, 3'b0000,power_on_ok, n_Rst_Botton_Reset ,  b_WDT_OverTime , nReq_Reset };
		ADDR_WDT_Time_Cnt		:	i2c_rd_data_reg <= { WDT_Time_Cnt };
		default: i2c_rd_data_reg <= 8'hFF;
	endcase
end


always @( posedge Clk )
begin
	rd_en <= i2c_rd_request && i2c_rd_wr_sign;
	i2c_data_rd_valid <= rd_en;
	i2c_rd_data <= i2c_rd_data_reg;
end



//******************************************************
//I2C slave component
 i2c_slave i2c_slave_ins(    							
	//global  signal 
	.clk                (Clk),      				//I 
	.rst                (~nRst),           		//I  
    //port to the i2c interface
	.sda_io             (I2C_SDA_SLAVE),           	//B
	.scl_in             (I2C_SCL_SLAVE),              	//I
    //port to the ptp_sys_ctrl module
	.fpga_device_addr   (fpga_device_addr),     		//I 
	//port to the ptp_sys_ctrl module
	.i2c_rd_request     (i2c_rd_request),      		//O
	.i2c_rd_wr_addr     (i2c_rd_wr_addr),      		//O
	.i2c_data_rd_valid  (i2c_data_rd_valid),   		//I
	.i2c_rd_data        (i2c_rd_data),         		//I
	.i2c_wr_data_valid  (i2c_wr_data_valid),   		//O
	.i2c_wr_data        (i2c_wr_data),         		//O
	.i2c_rd_wr_sign     (i2c_rd_wr_sign)       		//O
     );
//******************************************************

endmodule